<template>
  <div id="app">
    <h1>DXF 文件解析示例</h1>
    <div id="svg"></div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import axios from 'axios'
import { SVG } from '@svgdotjs/svg.js'
import '@svgdotjs/svg.panzoom.js'
import '@svgdotjs/svg.select.js'
import svgPanZoom from 'svg-pan-zoom'

// 响应式数据
const dxfData = ref<any>(null)
const errorMessage = ref<string | null>(null)
const viewBox = ref({ x: 0, y: 0, width: 0, height: 0 })
const entitiesLayer0 = ref<any[]>([])
const entitiesBooth = ref<any[]>([])
const entitiesBoothNumber = ref<any[]>([])
const currentScaleValue = ref<number>(0)
const entitiesLayer0LWPOLYLINE = ref<any[]>([])
const entitiesLayer0LINE = ref<any[]>([])
const entitiesLayer0ARC = ref<any[]>([])
// 添加 svg-pan-zoom 实例引用
const panZoomInstance = ref<any>(null)

const zoomFactor = ref<number>(0.05)
// 封装方法：加载并解析 DXF 文件
const loadAndParseDxf = async () => {
  try {
    // 加载文件
    const response = await axios.get('/dxf.json')
    console.log('文件加载完成')

    // 解析文件
    // const parser = new DxfParser() // 使用默认导入的
    // const result = parser.parse(response.data)

    const result = response.data
    // 保存解析结果
    // dxfData.value = result
    const minX = result.header.$EXTMIN.x
    const minY = result.header.$EXTMIN.y
    const maxX = result.header.$EXTMAX.x
    const maxY = result.header.$EXTMAX.y
    const width = maxX - minX // ≈ 97272
    const height = maxY - minY // ≈ 131476.06
    viewBox.value = { x: minX, y: minY, width, height }
    classifyEntities(result.entities)
    errorMessage.value = null
    renderSVG()
    // renderSVG(viewBox)
  } catch (error) {
    // 错误处理
    console.error('加载或解析 DXF 文件失败:', error)
    errorMessage.value = '加载或解析 DXF 文件失败，请检查文件路径或格式。'
  }
}

const renderSVG = () => {
  // 获取容器的实际尺寸，或设置固定尺寸
  const container = document.getElementById('svg')
  const containerWidth = container?.clientWidth || 1000
  const containerHeight = container?.clientHeight || 1000
  const draw = SVG().addTo('#svg').size('100%', '100%')
  // 翻转Y轴：使用负的Y坐标和负的高度
  // 正确的翻转ViewBox方法：保持原始坐标，但翻转Y轴方向
  draw.attr('id', 'main-svg')
  draw.viewbox(
    `${viewBox.value.x} ${viewBox.value.y} ${viewBox.value.width} ${viewBox.value.height}`,
  )

  // 2. 对整个 SVG 应用 Y 轴翻转
  // draw.transform({
  //   flip: 'y', // 直接翻转Y轴
  //   origin: 'center' as any, // 翻转原点设为中点
  // })

  // 计算合适的初始缩放比例
  const scaleX = containerWidth / viewBox.value.width
  const scaleY = containerHeight / viewBox.value.height
  const initialScale = Math.min(scaleX, scaleY) * 0.9 // 留一些边距
  currentScaleValue.value = initialScale

  // 配置 panZoom
  // draw
  //   .panZoom({
  //     zoomMin: initialScale * 0.1, // 最小缩放为初始缩放的 10%
  //     zoomMax: initialScale * 20, // 最大缩放为初始缩放的 10 倍
  //     zoomFactor: zoomFactor.value,
  //   })
  //   .on('zoom', (evt: any) => {
  //     // console.log('zoom:', evt.detail)
  //   })
  //
  // // 设置初始缩放以适应内容
  // ;(draw as any).zoom(initialScale, { animation: true })

  // 渲染展位外围

  filterLayer0(entitiesLayer0.value)
  const mainGroup = draw.group().attr({ id: 'main-group' })
  const originX = viewBox.value.x + viewBox.value.width / 2
  const originY = viewBox.value.y + viewBox.value.height / 2
  mainGroup.transform({ scaleY: -1, origin: [originX, originY] })

  // 创建三个独立的 <g> 容器
  const groupOuter = mainGroup.group().attr({ id: 'group-outer' })
  const groupBooths = mainGroup.group().attr({ id: 'group-booths' })
  const groupBoothNumbers = mainGroup.group().attr({ id: 'group-booth-numbers' })
  // 在所有内容添加完成后，对主容器应用Y轴翻转

  entitiesLayer0LWPOLYLINE.value.forEach((entity) => {
    if (entity.shape === true) {
      groupOuter.polygon(entity.points).fill('none').stroke({ color: '#0a0', width: 30 })
    } else {
      groupOuter.polyline(entity.points).fill('none').stroke({ color: '#0a0', width: 30 })
    }
  })

  entitiesLayer0ARC.value.forEach((entity) => {
    console.log('Processing ARC:', entity)
    const pathData = createArcPath(
      entity.center.x,
      entity.center.y,
      entity.radius,
      entity.startAngle,
      entity.endAngle,
    )
    console.log('Generated path:', pathData)
    groupOuter.path(pathData).fill('none').stroke({ color: '#ff0000', width: 30 })
  })

  entitiesLayer0LINE.value.forEach((entity) => {
    groupOuter.line(entity.points).stroke({ color: '#0a0', width: 30 })
  })

  // 渲染展位
  entitiesBooth.value.forEach((entity) => {
    groupBooths.polygon(entity.points).fill('#0a0').stroke({ color: '#000', width: 30 })
  })

  // 渲染展位号（处理Y轴翻转）
  entitiesBoothNumber.value.forEach((entity) => {
    console.log('Processing text entity:', entity)
    if (
      entity.startPoint &&
      typeof entity.startPoint.x === 'number' &&
      typeof entity.startPoint.y === 'number'
    ) {
      const textElement = groupBoothNumbers

        .text(entity.text)
        .font({ size: entity.textHeight })
        .fill('#f06')
        .move(entity.startPoint.x, entity.startPoint.y)

      // 由于整个SVG被Y轴翻转，需要对文本再次翻转以保持正常显示
      textElement.transform({ scaleY: -1 })
    } else {
      console.warn('Invalid or missing start position for booth number:', entity)
    }
  })

  panZoomInstance.value = svgPanZoom('#main-svg', {
    zoomEnabled: true,
    controlIconsEnabled: true,
    fit: true,
    center: true,
    minZoom: 0.1,
    maxZoom: 20,
    zoomScaleSensitivity: 0.2,
    dblClickZoomEnabled: true,
    mouseWheelZoomEnabled: true,
    preventMouseEventsDefault: true,
    onZoom: (scale: number) => {
      console.log('当前缩放比例:', scale)
      currentScaleValue.value = scale
    },
    onPan: (point: { x: number; y: number }) => {
      console.log('当前平移位置:', point)
    },
  })
  // draw.select()
}

// 分类方法
const classifyEntities = (entities: any[]) => {
  entities.forEach((entity) => {
    if (entity.layer === '0') {
      entitiesLayer0.value.push(entity)
    } else if (entity.layer === '展位') {
      entity.points = generatePolygonPoints(entity.vertices)
      entitiesBooth.value.push(entity)
    } else if (entity.layer === '展位号') {
      entitiesBoothNumber.value.push(entity)
    } else {
      // 可选：处理未知 layer 类型
      console.warn('Unknown layer:', entity.layer)
    }
  })
}

const filterLayer0 = (entities: any[]) => {
  entities.forEach((entity) => {
    if (entity.type === 'LWPOLYLINE') {
      entity.points = generatePolygonPoints(entity.vertices)
      entitiesLayer0LWPOLYLINE.value.push(entity)
    } else if (entity.type === 'LINE') {
      entity.points = generatePolygonPoints(entity.vertices)
      entitiesLayer0LINE.value.push(entity)
    } else if (entity.type === 'ARC') {
      entitiesLayer0ARC.value.push(entity)
    }
  })
}

// 将顶点数组转换为 SVG polygon 的 points 字符串
const generatePolygonPoints = (vertices: { x: number; y: number }[]): string => {
  return vertices.map((v) => `${v.x},${v.y}`).join(' ')
}

const createArcPath = (
  centerX: number,
  centerY: number,
  radius: number,
  startAngle: number,
  endAngle: number,
) => {
  console.log('createArcPath inputs:', { centerX, centerY, radius, startAngle, endAngle })

  // DXF角度通常是弧度，但需要处理Y轴翻转
  // 由于整个SVG进行了Y轴翻转，需要调整角度方向
  const adjustedStartAngle = -startAngle
  const adjustedEndAngle = -endAngle

  const startX = centerX + radius * Math.cos(adjustedStartAngle)
  const startY = centerY + radius * Math.sin(adjustedStartAngle)
  const endX = centerX + radius * Math.cos(adjustedEndAngle)
  const endY = centerY + radius * Math.sin(adjustedEndAngle)

  // 计算角度差
  let angleDiff = Math.abs(adjustedEndAngle - adjustedStartAngle)

  // 判断是否为大弧（> 180°）
  const largeArcFlag = angleDiff > Math.PI ? 1 : 0

  // 确定扫描方向
  const sweepFlag = adjustedEndAngle > adjustedStartAngle ? 1 : 0

  const pathData = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${endX} ${endY}`
  console.log('Generated path data:', pathData)

  return pathData
}

onMounted(() => {
  loadAndParseDxf() // 页面加载时自动执行
})
</script>

<style scoped>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  text-align: left;
  padding: 20px;
  height: 100vh;
}

pre {
  background-color: #f4f4f4;
  padding: 10px;
  overflow-x: auto;
}

#svg {
  width: 100%;
  height: 100%;
  border: 1px solid #ccc;
}

/* 如果需要让文本保持正常方向，可以对文本元素再次翻转 */
/* 只对SVG内容应用Y轴翻转，不影响svg-pan-zoom控制按钮 */
</style>
